package com.jflm.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * ******************  类说明  *********************
 * class       :  ParamsHelper
 * @author     :  lfh
 * @version    :  1.0
 * description :  参数处理工具类
 * @see        :
 * ***********************************************
 */
public class ParamsHelper {
    private static final Logger logger = LoggerFactory.getLogger(ParamsHelper.class);

    private final static List<String> DEFAULT_IGNORE_FIELDS = new ArrayList<String>();

    static {
        DEFAULT_IGNORE_FIELDS.add("sign");
        DEFAULT_IGNORE_FIELDS.add("SIGN");
        DEFAULT_IGNORE_FIELDS.add("SIGNEXT");
        DEFAULT_IGNORE_FIELDS.add("class"); // debug时发现SpringBoot会把class全路径带回去
    }

    /**
     * 生成签名后的字符串,MD5加密<br/>
     * 待签名参数按照字母顺序排列
     *
     * @param paramMap 待签名参数
     * @param key 密钥
     *
     */
    public static String makeSign(Map<String, String> paramMap, String key) {
        String toSign = makeToSignString(paramMap, key);
        if(logger.isDebugEnabled()){
            logger.debug("#makeSign() 待签名串:{}", toSign);
        }
        return DigestUtils.md5Hex(toSign);
    }

    /**
     * 组装待签名参数字符串,过滤sign字段,未加签名密钥(key)
     *
     * @param paramMap 参数
     *
     */
    public static String makeToSignString(Map<String, String> paramMap) {
        return makeToSignString(paramMap, DEFAULT_IGNORE_FIELDS);
    }

    /**
     * 组装待签名参数字符串,过滤sign字段,加上签名密钥(key)
     *
     * @param paramMap 参数
     *
     */
    public static String makeToSignString(Map<String, String> paramMap, String key) {
        String toSignStr = makeToSignString(paramMap, DEFAULT_IGNORE_FIELDS);
        if(StringUtils.isBlank(toSignStr)){
            return StringUtils.EMPTY;
        }
        StringBuilder builder = new StringBuilder(toSignStr);
        builder.append("&key=").append(key);
        return builder.toString();
    }

    /**
     * 组装待签名参数字符串
     *
     * @param paramMap 参数
     * @param ignoreFields 不参与签名的字段,可为null
     *
     */
    public static String makeToSignString(Map<String, String> paramMap, List<String> ignoreFields) {
        //组装用于签名的参数
        List<String> paramList = new ArrayList<String>();
        //全部字段参与签名
        String fieldValue = null;
        if (CollectionUtils.isEmpty(ignoreFields)) {
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                fieldValue = StringUtils.trimToEmpty(entry.getValue());
                if (StringUtils.isBlank(entry.getKey())) {
                    continue;
                }
                paramList.add(entry.getKey().trim() + "=" + fieldValue);
            }
        } else {
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                fieldValue = StringUtils.trimToEmpty(entry.getValue());
                if (StringUtils.isBlank(entry.getKey())) {
                    continue;
                }
                if (ignoreFields.contains(entry.getKey().trim())) {
                    continue;
                }
                paramList.add(entry.getKey().trim() + "=" + fieldValue);
            }
        }
        //所有字段按字典顺序排序
        Collections.sort(paramList, new Comparator<String>() {
            public int compare(String o1, String o2) {
                if (o1 == null && o2 == null) {
                    return 0;
                }
                if (o1 == null && o2 != null) {
                    return -1;
                }
                if (o1 != null && o2 == null) {
                    return 1;
                }
                return o1.compareToIgnoreCase(o2);
            }
        });

        //组装待签名字符串
        StringBuilder builder = new StringBuilder();
        boolean isFirst = true;
        for (String element : paramList) {
            if (isFirst) {
                isFirst = false;
            } else {
                builder.append("&");
            }
            builder.append(element);
        }
        return builder.toString();
    }

    /**
     * 验证签名,MD5加密<br/>
     * 待签名参数按照字母顺序排列
     *
     * @param paramMap 待签名参数
     * @param key 密钥
     * @param sign 待验证签名串
     * @return 返回码,成功返回0000,失败返回对应的返回码
     */
    public static String verifySign(Map<String, String> paramMap, String key, String sign) {
        String toSign = makeToSignString(paramMap, key);
        if(logger.isDebugEnabled()){
            logger.debug("#makeSign() 待签名串:{}", toSign);
        }
        String signStr =  DigestUtils.md5Hex(toSign);
        if(StringUtils.equals(signStr, sign)){//签名通过
            if(logger.isDebugEnabled()){
                logger.debug("#makeSign() 验签通过.");
            }
            return ContantRC.SUCCESS;
        }
        return ContantRC.VERIFICATION_CODE_ERR;
    }

    /**
     * ********************************************
     * method name   : makeToUrlParams
     * description   : 参数转换为url提交的参数形式,p=v&p1=v1...
     * @return       : String
     * @param        : @param paramMap
     * modified      : lfh ,  2017年5月20日  15:00
     * @see          :
     * *******************************************
     */
    public static String makeToUrlParams(Map<String, String> paramMap) {
        StringBuilder builder = new StringBuilder();
        boolean isFirst = true;
        String key = null;
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            if(StringUtils.isBlank(entry.getKey())){
                continue;
            }

            if (isFirst) {
                isFirst = false;
            } else {
                builder.append("&");
            }

            key = StringUtils.trimToEmpty(entry.getKey());
            builder.append(key).append("=").append(StringUtils.trimToEmpty(entry.getValue()));
        }
        return builder.toString();
    }


}
